package com.atguigu.java;

/**
 *      面向对象特征之三：多态性
 *          1.理解多态性：可以理解为一个事物的多种形态
 *          2.何为多态性：
 *              对象的多态性：父类的引用指向子类的对象(或子类的对象赋给父类的引用)
 *          3.多态的使用：虚拟方法调用
 *              有了对象的多态性以后，
 *              我们在编译期，只能调用父类中声明的方法；
 *              但在运行期，我们实际执行的是子类重写父类的方法
 *
 *              总结：编译，看左边；运行，看右边。
 *
 *          4.多态性使用的前提：
 *              4.1 类的继承关系
 *              4.2 方法的重写
 *
 *          5.对象的多态性，只适用于方法，不适用于属性(编译和运行都看左边)
 *
 *          ***************************************************************************************************
 *
 *
 *
 *
 * @author : leimingchao
 * @date Date : 2021年08月25日 0:03
 */
public class PersonTest {

    public static void main(String[] args) {
        Person person = new Person();
        person.eat();
        System.out.println();
        Man man = new Man();
        man.eat();
        man.age = 25;
        man.earnMoney();
        //*******************************************************
        System.out.println("**********************");
        //对象的多态性：父类的引用指向子类的对象
        Person person1 = new Man();
        // Person person2 = new Woman();
        //多态的使用：当调用子父类同名同参数的方法时，实际执行的是子类重写父类的方法------>虚拟方法调用
        person1.eat();
        person1.walk();

        System.out.println(person1.id);
        System.out.println("****************************************************************");
        //不能调用子类所特有的方法、属性，编译时，person1是Person类型
        // person1.earnMoney();
        //有了对象的多态性以后，内存中实际上是加载了子类特有的属性和方法的，但是由于变量声明为父类类型
        //导致编译时，只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。

        //如何才能调用子类特有的属性和方法？
        //向下转型：使用强制类型转换符
        Man man1 = (Man) person1;
        man1.earnMoney();
        man1.isSmoking = true;

        //使用强转时，可能出现ClassCastException的异常
        // Woman woman = (Woman) person1;
        // woman.goShopping();

        /**
         * instanceof关键字的使用
         * a instanceof A:判断对象a是否是类A的实例，如果是，返回true；如果不是，返回false
         *
         * 使用情境：为了避免在向下转型时出现ClassCastException的异常，我们在向下转型之前
         * 先进行instanceof的判断，一旦返回true，就进行向下转型。如果返回false，不进行向下转型
         *
         *
         * 如果 a instanceof A 返回true，则 a instanceof B 也返回true
         * 其中，类B是类A的父类
         *
         *
         *
         */
        if (person1 instanceof Woman) {
            Woman woman = (Woman) person1;
            woman.goShopping();
            System.out.println("*****Woman*******");
        }

        if (person1 instanceof Man) {
            Man man2 = (Man) person1;
            man2.earnMoney();
            System.out.println("*****Man*******");
        }

        if (person1 instanceof Person) {
            System.out.println("*****Person*******");
        }

        if (person1 instanceof Object) {
            System.out.println("*****Object*******");
        }
        //练习：
        //问题一：编译时通过，运行时不通过
        //举例一：
        // Person person3 = new Woman();
        // Man man3 = (Man) person3;
        //举例二：
        // Person person4 = new Person();
        // Man man4 = (Man) person4;

        //问题二：编译通过，运行时也通过
        Object object = new Woman();
        Person p = (Person) object;

        //问题三：编译不通过
        // Man man5 = new Woman();

        // String str = new Date();

        // Object o = new Date();
        // String str1 = (String) o;
    }
}
